﻿(function ($) {
    $.jqplot.StepRenderer = function () {
        $.jqplot.LineRenderer.call(this);
    };

    $.jqplot.StepRenderer.prototype = new $.jqplot.LineRenderer();
    $.jqplot.StepRenderer.prototype.constructor = $.jqplot.StepRenderer;
    $.jqplot.StepRenderer.base = $.jqplot.LineRenderer.prototype;

    $.jqplot.StepRenderer.prototype.makeGridData = $.jqplot.LineRenderer.prototype.makeGridData;
    // called within scope of series.
    $.jqplot.StepRenderer.prototype.draw = function (ctx, gd, options) {
        var i;
        var opts = (options != undefined) ? options : {};
        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;
        var fill = (opts.fill != undefined) ? opts.fill : this.fill;
        var fillAndStroke = (opts.fillAndStroke != undefined) ? opts.fillAndStroke : this.fillAndStroke;
        var xmin, ymin, xmax, ymax;
        ctx.save();
        if (gd.length) {
            if (showLine) {
                if (this.step) {
                    var gdWithSteps = [];
                    var lastPoint = null;
                    for (i = 0; i < gd.length; i++) {
                        var point = gd[i];

                        if (lastPoint != null) {
                            if (point[1] != lastPoint[1]) {
                                var phantom = [point[0], lastPoint[1]];
                                phantom.noMarker = true;
                                gdWithSteps.push(phantom);
                            }
                        }

                        gdWithSteps.push(point);

                        lastPoint = point;
                    }

                    var previousPointToLast = this.data[this.data.length - 1];
                    var previousPointToLastDate = new Date(previousPointToLast[0]);
                    var contractEndDateMonth = previousPointToLastDate.getMonth() + 1;

                    // work out quarter contract end month
                    var periodName = this.data[0][2];
                    if (periodName != null && periodName.indexOf('Q') > -1) {
                        contractEndDateMonth = (Math.floor((contractEndDateMonth - 1) / 3) + 1) * 3;
                    }
                    // get final date of contract
                    var contractEndDate = new Date(previousPointToLastDate.getFullYear(), contractEndDateMonth, 0);
                    var lastGridData = this._xaxis.series_u2p(contractEndDate.getTime());
                    // Add a final step from the last point, to end on the final day of the contract
                    var phantom = [lastGridData, lastPoint[1]];
                    phantom.noMarker = true;
                    gdWithSteps.push(phantom);

                    gd = gdWithSteps;
                }

                // if we fill, we'll have to add points to close the curve.
                if (fill) {
                    if (this.fillToZero) {
                        // have to break line up into shapes at axis crossings
                        var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors);
                        var negativeColor = negativeColors.get(this.index);
                        if (!this.useNegativeColors) {
                            negativeColor = opts.fillStyle;
                        }
                        var isnegative = false;
                        var posfs = opts.fillStyle;

                        // if stoking line as well as filling, get a copy of line data.
                        if (fillAndStroke) {
                            var fasgd = gd.slice(0);
                        }
                        // if not stacked, fill down to axis
                        if (this.index == 0 || !this._stack) {

                            var tempgd = [];
                            this._areaPoints = [];
                            var pyzero = this._yaxis.series_u2p(this.fillToValue);
                            var pxzero = this._xaxis.series_u2p(this.fillToValue);

                            if (this.fillAxis == 'y') {
                                tempgd.push([gd[0][0], pyzero]);
                                this._areaPoints.push([gd[0][0], pyzero]);

                                for (var i = 0; i < gd.length - 1; i++) {
                                    tempgd.push(gd[i]);
                                    this._areaPoints.push(gd[i]);
                                    // do we have an axis crossing?
                                    if (this._plotData[i][1] * this._plotData[i + 1][1] < 0) {
                                        if (this._plotData[i][1] < 0) {
                                            isnegative = true;
                                            opts.fillStyle = negativeColor;
                                        }
                                        else {
                                            isnegative = false;
                                            opts.fillStyle = posfs;
                                        }

                                        var xintercept = gd[i][0] + (gd[i + 1][0] - gd[i][0]) * (pyzero - gd[i][1]) / (gd[i + 1][1] - gd[i][1]);
                                        tempgd.push([xintercept, pyzero]);
                                        this._areaPoints.push([xintercept, pyzero]);
                                        // now draw this shape and shadow.
                                        if (shadow) {
                                            this.renderer.shadowRenderer.draw(ctx, tempgd, opts);
                                        }
                                        this.renderer.shapeRenderer.draw(ctx, tempgd, opts);
                                        // now empty temp array and continue
                                        tempgd = [[xintercept, pyzero]];
                                        // this._areaPoints = [[xintercept, pyzero]];
                                    }
                                }
                                if (this._plotData[gd.length - 1][1] < 0) {
                                    isnegative = true;
                                    opts.fillStyle = negativeColor;
                                }
                                else {
                                    isnegative = false;
                                    opts.fillStyle = posfs;
                                }
                                tempgd.push(gd[gd.length - 1]);
                                this._areaPoints.push(gd[gd.length - 1]);
                                tempgd.push([gd[gd.length - 1][0], pyzero]);
                                this._areaPoints.push([gd[gd.length - 1][0], pyzero]);
                            }
                            // now draw this shape and shadow.
                            if (shadow) {
                                this.renderer.shadowRenderer.draw(ctx, tempgd, opts);
                            }
                            this.renderer.shapeRenderer.draw(ctx, tempgd, opts);


                            // var gridymin = this._yaxis.series_u2p(0);
                            // // IE doesn't return new length on unshift
                            // gd.unshift([gd[0][0], gridymin]);
                            // len = gd.length;
                            // gd.push([gd[len - 1][0], gridymin]);                   
                        }
                        // if stacked, fill to line below 
                        else {
                            var prev = this._prevGridData;
                            for (var i = prev.length; i > 0; i--) {
                                gd.push(prev[i - 1]);
                                // this._areaPoints.push(prev[i-1]);
                            }
                            if (shadow) {
                                this.renderer.shadowRenderer.draw(ctx, gd, opts);
                            }
                            this._areaPoints = gd;
                            this.renderer.shapeRenderer.draw(ctx, gd, opts);
                        }
                    }
                    else {
                        // if stoking line as well as filling, get a copy of line data.
                        if (fillAndStroke) {
                            var fasgd = gd.slice(0);
                        }
                        // if not stacked, fill down to axis
                        if (this.index == 0 || !this._stack) {
                            // var gridymin = this._yaxis.series_u2p(this._yaxis.min) - this.gridBorderWidth / 2;
                            var gridymin = ctx.canvas.height;
                            // IE doesn't return new length on unshift
                            gd.unshift([gd[0][0], gridymin]);
                            len = gd.length;
                            gd.push([gd[len - 1][0], gridymin]);
                        }
                        // if stacked, fill to line below 
                        else {
                            var prev = this._prevGridData;
                            for (var i = prev.length; i > 0; i--) {
                                gd.push(prev[i - 1]);
                            }
                        }
                        this._areaPoints = gd;

                        if (shadow) {
                            this.renderer.shadowRenderer.draw(ctx, gd, opts);
                        }

                        this.renderer.shapeRenderer.draw(ctx, gd, opts);
                    }
                    if (fillAndStroke) {
                        var fasopts = $.extend(true, {}, opts, { fill: false, closePath: false });
                        this.renderer.shapeRenderer.draw(ctx, fasgd, fasopts);
                        //////////
                        // TODO: figure out some way to do shadows nicely
                        // if (shadow) {
                        //     this.renderer.shadowRenderer.draw(ctx, fasgd, fasopts);
                        // }
                        // now draw the markers
                        if (this.markerRenderer.show) {
                            for (i = 0; i < fasgd.length; i++) {
                                if (!(fasgd[i].noMarker)) {
                                    this.markerRenderer.draw(fasgd[i][0], fasgd[i][1], ctx, opts.markerOptions);
                                }
                            }
                        }
                    }
                }
                else {
                    if (shadow) {
                        this.renderer.shadowRenderer.draw(ctx, gd, opts);
                    }

                    this.renderer.shapeRenderer.draw(ctx, gd, opts);
                }
            }
            // calculate the bounding box
            var xmin = xmax = ymin = ymax = null;
            for (i = 0; i < this._areaPoints.length; i++) {
                var p = this._areaPoints[i];
                if (xmin > p[0] || xmin == null) {
                    xmin = p[0];
                }
                if (ymax < p[1] || ymax == null) {
                    ymax = p[1];
                }
                if (xmax < p[0] || xmax == null) {
                    xmax = p[0];
                }
                if (ymin > p[1] || ymin == null) {
                    ymin = p[1];
                }
            }
            this._boundingBox = [[xmin, ymax], [xmax, ymin]];

            // now draw the markers
            if (this.markerRenderer.show && !fill) {
                for (i = 0; i < gd.length; i++) {
                    if (!(gd[i].noMarker)) {
                        this.markerRenderer.draw(gd[i][0], gd[i][1], ctx, opts.markerOptions);
                    }
                }
            }
        }

        ctx.restore();
    };

})(jQuery);